﻿
Imports System.Globalization
Imports System.Reflection
Imports System.Data
Imports System.Data.Objects
Imports System.Collections
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.Windows.Forms
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Diagnostics
Imports System.Linq
Imports System.Text

''' <summary>
''' TypeConverter that shows a list of types that inherit from ObjectContext and
''' can be assigned to the ObjectContextType property.
''' </summary>
Public Class ObjectContextTypeTypeConverter
    Inherits ReferenceConverter

#Region "Constructors"

    Public Sub New()
        MyBase.New(GetType(Type))
    End Sub

#End Region

#Region "Overrides"

    Public Overrides Function GetStandardValuesSupported(ByVal context As ITypeDescriptorContext) As Boolean
        Return True
    End Function

    Public Overrides Function GetStandardValuesExclusive(ByVal context As ITypeDescriptorContext) As Boolean
        Return True
    End Function

    Public Overrides Function GetStandardValues(ByVal context As ITypeDescriptorContext) As StandardValuesCollection
        Dim values As New List(Of Type)()

        'Value for no data source
        values.Add(Nothing)

        'All types that derive from ObjectContext
        For Each t As Type In GetObjectContextTypes(context)
            values.Add(t)
        Next

        'Done
        Return New StandardValuesCollection(values)
    End Function

    Public Overrides Function CanConvertFrom(ByVal context As ITypeDescriptorContext, ByVal sourceType As Type) As Boolean
        Return sourceType Is GetType(String)
    End Function

    Public Overrides Function ConvertFrom(ByVal context As ITypeDescriptorContext, ByVal culture As CultureInfo, ByVal value As Object) As Object
        If TypeOf value Is String Then
            Dim values = GetObjectContextTypes(context)
            For Each t As Type In values
                If t.ToString() = DirectCast(value, String) Then
                    Return t
                End If
            Next
            Return Nothing
        End If
        Return MyBase.ConvertFrom(context, culture, value)
    End Function

    Public Overrides Function ConvertTo(ByVal context As ITypeDescriptorContext, ByVal culture As CultureInfo, ByVal value As Object, ByVal destinationType As Type) As Object
        If destinationType Is GetType(String) AndAlso TypeOf value Is Type Then
            Return value.ToString()
        End If
        Return MyBase.ConvertTo(context, culture, value, destinationType)
    End Function

    Private Function GetObjectContextTypes(ByVal context As ITypeDescriptorContext) As List(Of Type)
        Dim values = New List(Of Type)()
        Dim tds = TryCast(context.GetService(GetType(ITypeDiscoveryService)), ITypeDiscoveryService)
        If tds IsNot Nothing Then
            For Each t As Type In tds.GetTypes(GetType(ObjectContext), True)
                If t.IsPublic AndAlso t.IsVisible AndAlso Not t.IsAbstract Then
                    values.Add(t)
                End If
            Next
        End If
        Return values
    End Function

#End Region

End Class

